Use case: conversion in multimode DMA ¶
Description of usage ¶
|
HAL1 |
HAL2 |
|
|---|---|---|
|
Start conversion in multimode DMA |
Activate the ADC peripheral and start the conversion in multimode DMA using
|
Activate the ADC peripheral and start the conversion using
Note From this point, the ADC internal analog hardware is enabled, inducing a slight current consumption. Start the conversion with a trigger using:
Note The conversion trigger can be:
|
|
Calibration (optional) |
|
|
|
DMA transfer complete callback |
Implement the
|
Implement the
|
|
DMA half-transfer callback |
Implement the
|
Implement the
|
|
Retrieve conversion results |
Use
|
The conversion results are stored in the buffer specified in
|
|
Stop conversion |
Stop potential ongoing conversions on the regular and injected groups and disable the ADC peripheral using
|
If the conversion trigger is not a software start (such as from another peripheral like a timer), stop the conversion using
Stop the ADC using
|
|
Loop for multiple iterations |
N/A |
Multiple iterations for starting and stopping conversions are possible. Warning
If multiple conversions are required, do not fully stop the ADC using the
|
Sequence diagram ¶
Code snippet ¶
|
HAL1 |
HAL2 |
|---|---|
uint32_t adcBuffer[2];
int main(void)
{
// Add your Init and config code
if (HAL_ADCEx_MultiModeStart_DMA(&hadc_master, (uint32_t*)adcBuffer, 2) != HAL_OK)
{
/* Start Error */
Error_Handler();
}
}
/* Error Handler */
void Error_Handler(void)
{
while (1)
{
/* Stay in this loop in case of error */
}
}
/* ADC conversion complete callback */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
if (hadc->Instance == ADC1)
{
/* Process the ADC conversion results stored in adcBuffer */
uint32_t adcValue1 = adcBuffer[0];
uint32_t adcValue2 = adcBuffer[1];
/* Example: Print the ADC values (you can replace this with your own processing code) */
printf("ADC1 Value: %lu, ADC2 Value: %lu\n", adcValue1, adcValue2);
/* Stop the ADC conversion */
if (HAL_ADCEx_MultiModeStop_DMA(&hadc_master) != HAL_OK)
{
/* Stop Error */
Error_Handler();
}
}
}
|
uint32_t adcBuffer[2];
/* Loop for Multiple Iterations var */
uint32_t TestLoop = 3;
int main(void)
{
// Add your Init and config code
/* ADC activation */
HAL_ADC_MM_Start(&hadc_master);
while (TestLoop != 0)
{
/* ADC with DMA measurement */
if (HAL_ADC_MM_REG_StartConv_DMA(&hadc_master, (uint32_t*)adcBuffer, ADC_BUFFER_SIZE) != HAL_OK)
{
/* Start Error */
Error_Handler();
}
/* Wait time for ADC conversion */
HAL_Delay(5);
TestLoop--;
}
/* Stop ADC */
HAL_ADC_MM_Stop();
}
/* Error Handler */
void Error_Handler(void)
{
while (1)
{
/* Stay in this loop in case of error */
}
}
/* ADC conversion complete callback */
void HAL_ADC_REG_DataTransferCpltCallback(hal_adc_handle_t *hadc)
{
if (hadc->Instance == ADC1)
{
/* Process the ADC conversion results stored in adcBuffer */
uint32_t adcValue1 = adcBuffer[0];
uint32_t adcValue2 = adcBuffer[1];
/* Example: Print the ADC values (you can replace this with your own processing code) */
printf("ADC1 Value: %lu, ADC2 Value: %lu\n", adcValue1, adcValue2);
/* Stop the ADC conversion */
if (HAL_ADC_MM_REG_StopConv_DMA(&hadc_master) != HAL_OK)
{
/* Stop Error */
Error_Handler();
}
}
}
|
Key changes ¶
The split of the activate and start conversion in multimode DMA functions.
The split of the disable and stop conversion in multimode DMA functions.
![@startuml
participant "User application\n(thread mode)" as appli
participant "User application\n(handler mode)" as appli_IRQ
participant "<font color=green><b>HAL ADC</b></font>" as ADC
participant "<font color=green><b>HAL DMA</b></font>" as DMA
participant "System HW interruption" as interruption
group#Bisque #Linen ADC operation
appli->ADC : HAL_ADCEx_MultiModeStart_DMA()
note right
From this point, the ADC internal analog hardware is
enabled (inducing a slight current consumption) and
conversion in DMA mode starts.
end note
return
appli->ADC : HAL_ADCEx_Calibration_Start()
return
ADC->ADC : Enable ADC selected interruptions\nEnable DMA request\nEnable ADC conversion trigger
interruption <[#purple]-x? : <font color=purple><b>DMA IRQ event\n(transfer complete)
interruption -> appli_IRQ : DMAx_IRQHandler()
activate appli_IRQ #DarkSalmon
appli_IRQ -> DMA : HAL_DMA_IRQHandler()
DMA -> DMA : Clear flag
DMA->ADC : Callback function pointer
ADC -> appli_IRQ: HAL_ADC_ConvCpltCallback()
appli_IRQ -> appli_IRQ : User appli processing
appli_IRQ -> interruption : (Return from ISR)
deactivate appli_IRQ
appli->ADC : HAL_ADCEx_MultiModeStop_DMA()
return
end
@enduml](../../../../../_images/plantuml-5b8674618f922325853c92ed2e01b620125a17e1.png)
![@startuml
participant "User application\n(thread mode)" as appli
participant "User application\n(handler mode)" as appli_IRQ
participant "<font color=green><b>HAL ADC</b></font>" as ADC
participant "<font color=green><b>HAL DMA</b></font>" as DMA
participant "System HW interruption" as interruption
group#Bisque #Linen ADC operation
appli->ADC : HAL_ADC_MM_Start()
note right
From this point, the ADC internal analog hardware is
enabled (inducing a slight current consumption).
end note
return
appli->ADC : HAL_ADC_MM_Calibrate()
return
loop#lightgrey Multiple iterations possible
appli->ADC : HAL_ADC_MM_REG_<color:purple>StartConv_DMA</color>() / _DMA_Opt()
note right
Iterate with HAL_ADC_MM_REG_StartConv() calls
end note
return
ADC->ADC : Enable ADC selected interruptions\nEnable DMA request\nEnable ADC conversion trigger
interruption <[#purple]-x? : <font color=purple><b>DMA IRQ event\n(transfer complete)
interruption -> appli_IRQ : DMAx_IRQHandler()
activate appli_IRQ #DarkSalmon
appli_IRQ -> DMA : HAL_DMA_IRQHandler()
DMA -> DMA : Clear flag
DMA->ADC : Callback function pointer
ADC -> appli_IRQ: HAL_ADC_REG_DataTransferCpltCallback()
appli_IRQ -> appli_IRQ : User appli processing
appli_IRQ -> interruption : (Return from ISR)
deactivate appli_IRQ
end
appli->ADC : HAL_ADC_MM_Stop()
return
end
@enduml](../../../../../_images/plantuml-96a029f5279df2a8afae22b95d5276138cff776b.png)
![@startuml
participant "User application\n(thread mode)" as appli
participant "User application\n(handler mode)" as appli_IRQ
participant "<font color=green><b>HAL ADC</b></font>" as ADC
participant "<font color=green><b>HAL DMA</b></font>" as DMA
participant "System HW interruption" as interruption
group#Bisque #Linen ADC operation
appli->ADC : HAL_ADC_MM_Start()
note right
From this point, the ADC internal analog hardware is
enabled (inducing a slight current consumption).
end note
return
appli->ADC : HAL_ADC_MM_Calibrate()
return
appli->ADC : HAL_ADC_MM_REG_<color:purple>StartConv_DMA</color>(<handle>, <buff_adr>, <buff_size>) / _DMA_Opt()
note right
Iterate with HAL_ADC_MM_REG_StartConv() calls
end note
return
loop#lightgrey Multiple iterations possible
ADC->ADC : Enable ADC selected interruptions\nEnable DMA request\nEnable ADC conversion trigger
interruption <[#purple]-x? : <font color=purple><b>DMA IRQ event\n(transfer complete)
interruption -> appli_IRQ : DMAx_IRQHandler()
activate appli_IRQ #DarkSalmon
appli_IRQ -> DMA : HAL_DMA_IRQHandler()
DMA -> DMA : Clear flag
DMA->ADC : Callback function pointer
ADC -> appli_IRQ: HAL_ADC_REG_DataTransferCpltCallback()
appli_IRQ -> appli_IRQ : User appli processing
appli_IRQ -> interruption : (Return from ISR)
deactivate appli_IRQ
appli->ADC : HAL_ADC_MM_REG_<color:purple>StopConv_DMA</color>()
return
end
appli->ADC : HAL_ADC_MM_Stop()
return
end
@enduml](../../../../../_images/plantuml-e97c5fdc29e0760bc764f258e3b242ce024d2e56.png)